/*
 * =====================================================================================
 *
 *       Filename:  main.c
 *
 *    Description:  software demux for MPEG2 TS, only get PTS and PCR info
 *
 *        Version:  1.0
 *        Created:  2009.01.01 14:52:36
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Derek Yang 
 *        Company:  HOME
 * =====================================================================================
 */

#include <stdio.h>
#include <stdint.h>
//#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>

#include "avdl_timmod_pvt_structs.h"
#include "timmod_test.h"

#define BUFFER_SIZE 10*1024 
#define PACKET_SIZE 200
#define MAX_PROG  1024
#define INFO_NUM	(BUFFER_SIZE/40)
#define PES_BUF_SIZE 20

#define IS_SYNC_WORD(A) ((A)==0x47)

//stream id type
#define IS_PROG_STRM_MAP(A) ((A)==0xBC)
#define IS_PAD_STRM(A) ((A)==0xBE)
#define IS_PRVT_STRM(A) ((A)==0xBF)
#define IS_ECM(A) ((A)==0xF0)
#define IS_EMM(A) ((A)==0xF1)
#define IS_DSMCC_STRM(A) ((A)==0xF2)
#define IS_TYPE_E_STRM(A) ((A)==0xF8)
#define IS_PROG_STRM_DIR(A) ((A)==0xFF)

#define __DEBUG_ME__


struct prog_in_buffer{
	uint64_t pts_value[INFO_NUM];
	uint64_t pcr_value[INFO_NUM];
	uint32_t pcr_num;
	uint32_t pts_num;
	//1 for video ,2 for audio;
	uint32_t pts_type[INFO_NUM];
}prog_in_buffer;

struct descriptor{

	uint32_t buffer_bytes;
	bool last_one ;
	struct prog_in_buffer prog[MAX_PROG]; 
} descriptor; 

struct prog_info{
	uint32_t video_pid;
	uint32_t audio_pid;
	uint32_t pcr_pid;
	uint32_t pmt_pid;
	//uint32_t network_pid;
	uint32_t prog_num;
	uint32_t got_psi;
}prog_info;

static int32_t get_ts_buffer(FILE *,uint8_t *,struct descriptor *,int32_t ); 
static void handle_packet(const uint8_t *,struct descriptor *);
static bool get_pes_buffer(const uint8_t *,int32_t *,int32_t );
static uint64_t adaptation_filed(const uint8_t *,int32_t *);
static uint64_t get_pts(void);
static int32_t psi_data(const uint8_t *,struct descriptor *,int32_t *);
static int32_t pmt_data(const uint8_t *,int32_t *);
static uint32_t get_1_byte(const uint8_t *  ,int32_t *);
static uint32_t get_2_bytes(const uint8_t * ,int32_t *);
static uint32_t get_3_bytes(const uint8_t * ,int32_t *);
static uint32_t get_4_bytes(const uint8_t *  ,int32_t *);

struct prog_info program_info[MAX_PROG];
uint32_t program_idx;

uint64_t addr;
uint32_t got_psi;//1 for 1st PMT,2 for the 2nd pass 
uint8_t pes_buf[PES_BUF_SIZE];//enough for PTS&DTS 
//uint8_t pes_buf1[PES_BUF_SIZE];//enough for PTS&DTS 
uint32_t pes_buf_ptr;
//uint32_t pes_buf1_ptr;
int32_t main (int32_t argc,char *argv[])
{

	struct descriptor cur_buf_desc/*, prv_buf_desc*/;
	FILE *ts_stream;
#ifdef __DEBUG_ME__
	FILE *ts_stream_debug;
	FILE *pts_info_fp;
	FILE *pcr_info_fp;
#endif
	uint8_t ts_buffer[BUFFER_SIZE];
	uint8_t ts_packet[PACKET_SIZE];
	//uint8_t *ts_location = "./test.ts";
	char *ts_location; 
	if (2 == argc ){
		ts_location = argv[1];
	}else{
		printf("Usage:\n");
		printf("binary <TS file location>\n");
		return 0;
	}
#ifdef __DEBUG_ME__
	char *pts_info = "./pts_info.txt";
	char *pcr_info = "./pcr_info.txt";
#endif
	int32_t packet_bytes_num = 0;
	int32_t i,ii,jj;
	int32_t cc = 0;
	printf("##########   Start Program    ###########\n");
	got_psi = 0;
	memset(program_info,0,sizeof(program_info));
	memset(ts_packet,0,sizeof(ts_packet));
	program_idx = 0;
	

	while(1){
		if (program_idx && (program_idx == got_psi)){
			got_psi++;
			printf("2nd time pass,got_psi=%d\n",got_psi);
		}

		//0. open a TS for reading bytes
		if ( NULL == (ts_stream = fopen(ts_location,"rb"))){
			printf("CAN'T open %s \n",ts_location);
			return 0;
		}
#ifdef __DEBUG_ME__
		if ( NULL == (ts_stream_debug = fopen(ts_location,"rb"))){
			printf("CAN'T open %s \n",ts_location);
			return 0;
		}
		//open a file to write 
		//int32_t bytes_put;
		if ( NULL == (pts_info_fp = fopen(pts_info,"wt+"))){
			printf("CAN'T open %s \n",pts_info);
			return 0;
		}
		if ( NULL == (pcr_info_fp = fopen(pcr_info,"wt+"))){
			printf("CAN'T open %s \n",pcr_info);
			return 0;
		}
		
#endif
		//1. read TS into a buffer
		cur_buf_desc.last_one = false;
		memset(&ts_buffer,0,sizeof(ts_buffer));
		packet_bytes_num = 0;
		addr = 0;
		pes_buf_ptr = 0;
		while (!cur_buf_desc.last_one){
			//printf("packet bytes:%d\n",packet_bytes_num);
			//initialize the buffer descriptor
			memset(&cur_buf_desc,0,sizeof(cur_buf_desc));
			memcpy(ts_buffer,ts_packet,packet_bytes_num); 
			get_ts_buffer(ts_stream,&ts_buffer[packet_bytes_num],&cur_buf_desc,packet_bytes_num);
#ifdef __DEBUG_ME__
			printf("##### New Buffer ######\n");
#endif

			// handle a packet from TS
			for (i = 0; i < cur_buf_desc.buffer_bytes; ){
				//find a sync word(0x47)
				if (IS_SYNC_WORD(ts_buffer[i])){
					if (188 > (cur_buf_desc.buffer_bytes - i)){
						packet_bytes_num = cur_buf_desc.buffer_bytes - i;
						printf("packet_bytes_num:0x%x\n",packet_bytes_num);
						memcpy(ts_packet,&ts_buffer[i],packet_bytes_num);
						break;
					}
#ifdef __DEBUG_ME__
					printf("##### Packet Start Addr:0x%llx###\n",addr);
					for (ii = 0;ii < 4;ii++){
						 cc = fgetc(ts_stream_debug); 
						 //printf("%x ",cc);
						 if (cc  != (ts_buffer[i+ii]& 0x000000FF)){
							 printf("wrong as :%x\n",ts_buffer[i+ii] & 0x000000FF);
							 assert(0);
						 }
					}
					 //printf("\n");
					for (;ii < 188;ii++){
						 cc = fgetc(ts_stream_debug); 
					}


#endif
					//if (addr == 0x025974){
					//	printf("%x %x %x %x",ts_buffer[i- 188],ts_buffer[i - 187],ts_buffer[i - 186],ts_buffer[i - 185]);
						//exit(0);
					//}
					//if not a whole packet in the end of buffer, save it
					//get PTS & PCR from a TS packet
					handle_packet(&ts_buffer[i],&cur_buf_desc);
					i +=188;
					addr += 188;
				}else{
					i++;
					addr++;
					fgetc(ts_stream_debug); 
				}
				if (program_idx && (program_idx == got_psi)){
					break;
				}

			}//end of for
				if (program_idx && (program_idx == got_psi)){
					fclose(ts_stream);
#ifdef __DEBUG_ME__
					fclose(ts_stream_debug);
					fclose(pts_info_fp);
					fclose(pcr_info_fp);
#endif
					break;
				}
			if (program_idx && (program_idx < got_psi)){
			//	fprintf(fp_dbg,"######### ################\n");
				for (jj = 0; jj < program_idx; jj++){
					for (ii = 0;ii < cur_buf_desc.prog[jj].pts_num;ii++){
						fprintf(pts_info_fp,"PROG:%d\t",program_info[jj].prog_num);
						fprintf(pts_info_fp,(2 == cur_buf_desc.prog[jj].pts_type[ii]) ? "\t\tAudio" : "Video");
						fprintf(pts_info_fp," PTS:%lld\n", cur_buf_desc.prog[jj].pts_value[ii]);
					}
				}
				for (jj = 0; jj < program_idx; jj++){
					for (ii = 0;ii < cur_buf_desc.prog[jj].pcr_num;ii++){
						fprintf(pcr_info_fp,"PROG:%d\tPCR:%lld\n",
						program_info[jj].prog_num, cur_buf_desc.prog[jj].pcr_value[ii]);
					}
				}
			}

					//PTS and PCR type on this TS buffer detection 
					//				pts_type_detection;
					//				previou <= current
		}//end of while(!last_one)
		printf("got psi:%d\n",got_psi);
		if (program_idx && (program_idx < got_psi)){
			break;
		}

	}//end of while(1)
	//	printf("pts :%lld,pcr :%lld\n",cur_buf_desc.pts_value[0],cur_buf_desc.pcr_value[0]);
	//	printf("pts num:%d,pcr num:%d\n",cur_buf_desc.pts_num,cur_buf_desc.pcr_num);
	printf ("End of Stream, Quit\n");
	fclose(ts_stream);
#ifdef __DEBUG_ME__
	fclose(ts_stream_debug);
	fclose(pts_info_fp);
	fclose(pcr_info_fp);
#endif
	return 1;
}

static int32_t get_ts_buffer(FILE *fp,uint8_t *buffer,struct descriptor *buf_desc,int32_t num) 
{
	int32_t n;
	n = fread(buffer,sizeof(*buffer),BUFFER_SIZE - num,fp);
	if (feof(fp)){
		buf_desc->last_one = true;
		printf("It's the last buffer\n");
	}else {
		if (BUFFER_SIZE !=( n + num) ){
			printf("Seems error return %d!= %d in get_ts_buffer\n",n,BUFFER_SIZE);
		}
		buf_desc->last_one = false;
		//buf_desc->last_one = true;//for debug 1st buffer only
	}
	buf_desc->buffer_bytes = n + num;
	return 1;
}


// get PTS & PCR info from a packet
static void handle_packet(const uint8_t *packet_hdr,struct descriptor *buffer_info)
{
	//bool ts_error_indicator,,transport_priority;
	uint32_t pid = 0,adaptation_filed_control = 0, continiuty_counter = 0;
	uint64_t pcr_tmp = 0;
	uint32_t tmp = 0;
	int32_t packet_bytes_used  = 0;
	int32_t i,j,loop_num;
	bool unit_start_indicator;

	//the 1st byte
	//printf("******  DEBUG  *****\n");

	assert(IS_SYNC_WORD(*packet_hdr));

	tmp = get_4_bytes(packet_hdr,&packet_bytes_used) ;
	
	pid = (tmp >> 8) & 0x00001FFF;
	printf("PID:0x%x\n",pid);
	assert(!(pid & 0xFFFFE000));//pid should not more than 13bits
	unit_start_indicator = (tmp >> 22) & 0x1;
	//printf("unit start indicator:%d\n",unit_start_indicator);

	printf("tmp:%x\n",tmp);
	adaptation_filed_control = (tmp >> 4 ) & 0x3;
	continiuty_counter = tmp & 0xF;
	//printf("bytes used:%d\n",*bytes_used);
	printf("adapt filed ctrl:%d\n",adaptation_filed_control);

	if(adaptation_filed_control == 0x2 || adaptation_filed_control == 0x3){
		pcr_tmp = adaptation_filed(packet_hdr,&packet_bytes_used);

		for(j = 0; j < program_idx; j++){
			if ((0 != pcr_tmp) && (pid == program_info[j].pcr_pid)){
				printf("PCR PID:0x%x\tPCR:%lld\n",program_info[j].pcr_pid,pcr_tmp);
				buffer_info->prog[j].pcr_value[buffer_info->prog[j].pcr_num] = pcr_tmp; 
				buffer_info->prog[j].pcr_num++;
			}
		}
	}

	if(adaptation_filed_control == 0x1 || adaptation_filed_control == 0x3){
			if (!pid){//pid == 0 => PSI packet
				printf("PSI Packet:\n");
				psi_data(packet_hdr,buffer_info,&packet_bytes_used);
				return;
			}else if (0x1 == pid){
				//printf("CA Packet:\n");
			}else{
				for (j = 0; j < program_idx; j++){
					if (pid == program_info[j].pmt_pid){
						printf("PID:0x%x\n",pid);
						pmt_data(packet_hdr,&packet_bytes_used);
						if (!program_info[j].got_psi){
							//printf("got psi:%d\n",got_psi);
							program_info[j].got_psi = 1;
							got_psi++;
						}
					}else if ((pid == program_info[j].video_pid) || (pid == program_info[j].audio_pid )){
						//get a PES packet from several ts packet
						loop_num = 0;
						//printf("pes_buf_ptr:%d\t",pes_buf_ptr);
						if (unit_start_indicator) loop_num++;
						if (pes_buf_ptr) loop_num++;
						for (i = 0;i < loop_num;i++){

							if (get_pes_buffer(packet_hdr,&packet_bytes_used,i)){
								//get pts
								if (0 != (buffer_info->prog[j].pts_value[buffer_info->prog[j].pts_num] = \
										get_pts())){
								if (pid == program_info[j].audio_pid){
									buffer_info->prog[j].pts_type[buffer_info->prog[j].pts_num] = 2;//audio
									printf("PDI:0x%x\tAudio\t",pid);
								}else if (pid == program_info[j].video_pid){
									buffer_info->prog[j].pts_type[buffer_info->prog[j].pts_num] = 1;//video
									printf("PDI:0x%x\tVideo\t",pid);
								}
								printf("PTS:%lld\n",
										buffer_info->prog[j].pts_value[buffer_info->prog[j].pts_num]);
								buffer_info->prog[j].pts_num++;
								}
								pes_buf_ptr = 0;

							}
						}//end for (i
					}else if (0x1FFF == pid){
						//printf("NULL Packet\n");
					}else{
						//printf("Unkown Packet\n");
						//TODO:
					}
				}//end for(j
				return;
			}
	}
	//printf("byte used finally:%d\n",*bytes_used);
	return;
}
 
static uint64_t adaptation_filed(const uint8_t *packet_hdr,int32_t *num)
{
	uint32_t  fld_length = 0;
	uint32_t  tmp = 0,pcr_flag = 0;
	//uint32_t  opcr_flag = 0;
	uint64_t pcr_base = 0;
	//uint32_t transport_private_data_flag = 0,splicing_point_flag = 0;
	
	fld_length = get_1_byte(packet_hdr,num);
	printf("adaption length:%d,bytes used:%d\n",fld_length,*num);
	if (!fld_length){
		//printf("filed length == 0\n");
		return 0;
	}
	tmp = get_1_byte(packet_hdr,num);
	pcr_flag = (tmp >> 4 ) & 0x1;
	fld_length -=1;
	
	//opcr_flag = (tmp >> 3 ) & 0x1;
	if (pcr_flag){
		tmp = get_4_bytes(packet_hdr,num);
		pcr_base = (uint64_t)tmp;
		pcr_base =  (pcr_base << 1 ) & 0x00000001FFFFFFFEll;   
		tmp = get_2_bytes(packet_hdr,num);
		pcr_base |= ((uint64_t)(tmp >> 15)) & 0x0000000000000001ll;
		//pcr_ext  |= ((uint64_t)tmp & 0x00000000000001FF); 
		//pcr = pcr_base*300 + pcr_ext;
		printf("pcr_base=%lld\n",pcr_base);
		//printf("pcr_ext=%llx\n",pcr_ext);
		//printf("pcr=%llx\n",pcr);
		fld_length -= 6;
	}
	/*
	if (opcr_flag){
		get_4_bytes(packet_hdr,num);
		get_2_bytes(packet_hdr,num);
	}
	*/
	*num += fld_length;
		return pcr_base;

}
 
static int32_t psi_data(const uint8_t *packet_hdr,struct descriptor *buffer_des,int32_t *bytes_used)
{
	uint32_t table_id;
	int32_t section_length = 0,section_end = 0;
	//uint32_t cur_next_indictor = 0;
	int32_t program_num = 0;
	int32_t i;
	//int32_t program_map_pid = 0,net_work_pid = 0 ;
	//pointer field 
	//get_1_byte(packet_hdr,bytes_used);
	(*bytes_used)++;
	table_id = get_1_byte(packet_hdr,bytes_used);
	assert(0x0 == table_id);

	section_length = get_2_bytes(packet_hdr,bytes_used) & 0x00000FFF;  
	//printf("psi section length:%d\n",section_length);
	assert(section_length < 0x3fd);
	section_end = *bytes_used + section_length;

	//cur_next_indictor = get_3_bytes(packet_hdr,bytes_used) & 0x1; 
	//get_2_bytes(packet_hdr,bytes_used);
	//printf("bytes used:%d\n",*bytes_used);
	*bytes_used +=5;
	while (*bytes_used < (section_end - 4 )){
		//program num
		program_num = get_2_bytes(packet_hdr,bytes_used);
		printf("Program num:0x%x\n",program_num);
		if (program_num){
			//check whether if this is a new program or an old one
			for(i = 0; i < program_idx; i++){
				if (program_info[i].prog_num == program_num)
					break;
			}
			if (i == program_idx ){
//a new program
				program_idx++;
//TODO:open a timmod and 2 channales(audio and video only) for a program
				
				
			}
			//program map PID
			program_info[i].pmt_pid = get_2_bytes(packet_hdr,bytes_used) & 0x00001FFF;
			program_info[i].prog_num = program_num;
			printf("PMT PID:0x%x\n",program_info[i].pmt_pid);
		}else{
			//network pid
			 //program_info.network_pid = 
			printf("NetWork PID:0x%x\n",get_2_bytes(packet_hdr,bytes_used) & 0x00001FFF);
		}
	}
	//CRC
	*bytes_used +=4;
	return 0;
}

static int32_t pmt_data(const uint8_t *packet_hdr,int32_t *bytes_used)
{
	uint32_t tmp;
	int32_t i;
	int32_t section_length = 0,section_end = 0;
	int32_t program_num = 0;
	//pointer field
	//get_1_byte(packet_hdr,bytes_used);
	(*bytes_used)++;
	//table id
	tmp = get_1_byte(packet_hdr,bytes_used);
	assert(0x02 == tmp);
	//section length
	section_length = get_2_bytes(packet_hdr,bytes_used) & 0x00000FFF;  
	//printf("section length:%d\n",section_length);
	assert(section_length < 0x3fd);
	section_end = section_length + *bytes_used;
	//printf("section end:%d\n",section_end);

	program_num = get_2_bytes(packet_hdr,bytes_used);
	//get_3_bytes(packet_hdr,bytes_used);
	*bytes_used += 3;
	for(i = 0; i < program_idx;i++){
		if (program_num == program_info[i].prog_num){
			break;
		}
	}
	if (i == program_idx){//didn't get the program's pmt info yet
		return 0;
	}

	program_info[i].pcr_pid = get_2_bytes(packet_hdr,bytes_used) & 0x00001FFF;
	printf("pcr pid:0x%x\n",program_info[i].pcr_pid);
	//PMT descriptor length
	tmp = get_2_bytes(packet_hdr,bytes_used) & 0x00000FFF;
	//printf("PMT desc:%d\n",tmp);

	//*packet_hdr += tmp;
	*bytes_used += tmp;
	while ((section_end - 4) > *bytes_used){
		tmp = get_1_byte(packet_hdr,bytes_used);
		//printf("ES PID type:0x%x\n",tmp);
		switch (tmp){
			case 0x1:
			case 0x2:
			case 0x1B:
			case 0x1E:
				program_info[i].video_pid = get_2_bytes(packet_hdr,bytes_used) & 0x00001FFF;   
				printf("Video PID:0x%x\n",program_info[i].video_pid);
				break;
			case 0x3:
			case 0x4:
			case 0xF:
			case 0x11:
			case 0x1C:
				program_info[i].audio_pid = get_2_bytes(packet_hdr,bytes_used) & 0x00001FFF;   
				printf("Audio PID:0x%x\n",program_info[i].audio_pid);
				break;
			default:
				tmp = get_2_bytes(packet_hdr,bytes_used) & 0x00001FFF;
				printf("Unkown ES PID:0x%x\n",tmp); 
						break;
		}
		//ES descriptor length
		tmp = get_2_bytes(packet_hdr,bytes_used) & 0x00000FFF;
		//printf("ES desc:%d\n",tmp);
		//*packet_hdr += tmp;
		*bytes_used += tmp;
	}
	//CRC
	//get_4_bytes(packet_hdr,bytes_used);
	*bytes_used += 4;
	return 0;
}

static uint64_t get_pts(void)
{
	uint32_t tmp = 0,stream_id = 0;
	//pes_length = 0;
	int32_t pts_dts_flag = 0;
	int32_t num = 0;
	uint64_t pts = 0;
	const uint8_t *pes_hdr;
	pes_hdr = pes_buf;
	//printf("pes_buf_ptr:%d\t",pes_buf_ptr);
	//printf("%x,%x,%x,%x\n",pes_buf[0],pes_buf[1],pes_buf[2],pes_buf[3]);
	//printf("%x,%x,%x,%x\n",*pes_ptr,*(pes_ptr+1),*(pes_ptr+2),*(pes_ptr+3));
	tmp = get_3_bytes(pes_hdr,&num);
	if (0x1 != (tmp & 0x00FFFFFF)){
		tmp = tmp << 8;
		tmp |= get_1_byte(pes_hdr,&num);
	}
	assert (0x1 == (tmp & 0x00FFFFFF));
	
	stream_id = get_1_byte(pes_hdr,&num);
	num +=2;
	//pes_length = get_2_bytes(pes_hdr,&num);
	//printf("pes length:%d\n",pes_length);
	if (IS_PROG_STRM_MAP(stream_id) || IS_PAD_STRM(stream_id)   \
	 || IS_PRVT_STRM(stream_id)     || IS_ECM(stream_id)		\
 	 || IS_EMM(stream_id)			|| IS_DSMCC_STRM(stream_id) \
     || IS_TYPE_E_STRM(stream_id)	|| IS_PROG_STRM_DIR(stream_id)){
		return 0;
		//*packet_hdr += pes_length;
		//*bytes_used += pes_length;
	}else {
		tmp = get_3_bytes(pes_hdr,&num);
		pts_dts_flag = (tmp >> 14 ) & 0x3;

		if (0x2 == (pts_dts_flag & 0x2)){
			tmp = get_1_byte(pes_hdr,&num);
			//assert(pts_dts_flag == ((tmp >> 4) & 0x0000000F));
			pts =((uint64_t)(tmp & 0x0000000E)) << 29; 
			tmp = get_2_bytes(pes_hdr,&num);
			pts |=((uint64_t)(tmp & 0x0000FFFE)) << 14; 
			tmp = get_2_bytes(pes_hdr,&num);
			pts |=((uint64_t)(tmp & 0x0000FFFE)) >> 1; 
			printf("PTS in PES packet:0x%llx\n",pts);

		}
		//*packet_hdr += pes_length;
		//*bytes_used += pes_length;
	}
	return pts;
}
static bool get_pes_buffer(const uint8_t *ts_ptr,int32_t *bytes_used,int32_t loop_num)
{
	int32_t tmp = 0;
	//have start code in this packet
	//1.if this is the 2nd loop should have start code in this packet
	//2.if pes_buf_ptr ==0 means to fed the pes buffer with start code
	if (loop_num || (!pes_buf_ptr)){//get start code
			while (0x1 != (tmp & 0x00FFFFFF)){
				if (188 == *bytes_used){
					//printf("PES no Start Code:\n");
					//save the last 1 or 2 bytes of this packet. 
					pes_buf[0] = 0x00;
					pes_buf[1] = 0x00;
					pes_buf_ptr = 2;
					return false;
				}
				tmp = tmp << 8;
				tmp |= get_1_byte(ts_ptr,bytes_used);
			}
			pes_buf[0] = 0x00;
			pes_buf[1] = 0x00;
			pes_buf[2] = 0x01;
			pes_buf_ptr = 3;
			while (19 > pes_buf_ptr){
				if (188 == *bytes_used){
					//printf("not enough data in PES:\n");
					return false;
				}
				pes_buf[pes_buf_ptr] = get_1_byte(ts_ptr,bytes_used);
				pes_buf_ptr++;
			}
			return true;
	}
	////get pes data on residual of pes 
			while (  19 > pes_buf_ptr){
				if (188 == *bytes_used){
					//printf("not enough data in PES:\n");
					return false;
				}
				pes_buf[pes_buf_ptr] = get_1_byte(ts_ptr,bytes_used);
				pes_buf_ptr++;
			}
			return true;
}

static uint32_t get_1_byte(const uint8_t *ptr,int32_t *num)
{
	ptr += *num;
	*num += 1;
	return *ptr++ & 0x000000FF;
}
//little endian
static uint32_t get_2_bytes(const uint8_t *ptr,int32_t *num)
{
	uint32_t ret = 0;
	ptr += *num;
	*num += 2;
	ret = (*ptr++ << 8) & 0x0000FF00; 
	ret |= (*ptr++ ) & 0x000000FF ; 
	return ret & 0x0000FFFF;
}
//little endian
static uint32_t get_3_bytes(const uint8_t *ptr,int32_t *num)
{
	uint32_t ret = 0;
	ptr += *num;
	*num += 3;
	ret = (*ptr++ << 16) & 0x00FF0000; 
	ret |= (*ptr++ << 8) & 0x0000FF00; 
	ret |= (*ptr++ ) & 0x000000FF; 
	return ret & 0x00FFFFFF;
}
//little endian
static uint32_t get_4_bytes(const uint8_t *ptr,int32_t *num)
{
	uint32_t ret = 0;
	ptr += *num;
	*num += 4;
	ret  = (*ptr++ << 24) & 0xFF000000; 
	ret |= (*ptr++ << 16) & 0x00FF0000 ; 
	ret |= (*ptr++ << 8) & 0x0000FF00; 
	ret |= (*ptr++ ) & 0x000000FF; 
	return ret ;
}


